const { src, dest, parallel, series, watch } = require('gulp');
const del = require('del');
const browserSync = require('browser-sync');
const loadPlugin = require('gulp-load-plugins');

const plugin = loadPlugin();

const bs = browserSync.create();

const data = {
  menus: [
    {
      name: 'Home',
      icon: 'aperture',
      link: 'index.html',
    },
    {
      name: 'Features',
      link: 'features.html',
    },
    {
      name: 'About',
      link: 'about.html',
    },
    {
      name: 'Contact',
      link: '#',
      children: [
        {
          name: 'Twitter',
          link: 'https://twitter.com/w_zce',
        },
        {
          name: 'About',
          link: 'https://weibo.com/zceme',
        },
        {
          name: 'divider',
        },
        {
          name: 'About',
          link: 'https://github.com/zce',
        },
      ],
    },
  ],
  pkg: require('./package.json'),
  date: new Date(),
};

//清除任务依赖安装  yarn gulp del --dev
/**
 * 删除的废弃文件任务
 * @returns {Promise<string[]> | *}
 */
const clean = () => {
  return del(['dist', 'temp']);
};

//创建一个style的文件处理配置
/**
 * 样式编译的任务
 * @returns {*}
 */
const style = () => {
  //如果没有base参数的话 文件会被全部直接构建到dist目录下， 原本的目录结构就被丢失了
  //使用这个目录结构后会保存base的文件后面的所有目录结构
  //使用国base后 但是后缀名还没有转换 所以还需要将文件的后缀名转换了  这时就需要使用一个新的插件 gulp-plugin.sass
  //yarn add gulp-plugin.sass@4.1.0 --dev
  return src('src/assets/styles/*.scss', { base: 'src' })
    .pipe(plugin.sass({ outputStyle: 'expanded' }))
    .pipe(dest('temp'))
    .pipe(bs.reload({ stream: true })); //以流的方式推到浏览器 实现页面更新的效果
};

/**
 * 脚本编译的任务
 */
const script = () => {
  //script 文件流的写入
  //将ES6转化为普通函数
  //安装babel插件  yarn add gulp-plugin.babel @plugin.babel/core @plugin.babel/preset-env --dev
  return src('src/assets/scripts/*.js', { base: 'src' })
    .pipe(plugins.eslint())
    .pipe(plugins.eslint().format())
    .pipe(plugins.eslint().failAfterError())
    .pipe(plugin.babel({ presets: ['@babel/preset-env'] }))
    .pipe(dest('temp'))
    .pipe(bs.reload({ stream: true }));
};

//html模版文件的安装
// yarn add gulp-plugin.swig --dev
/**
 * html模版编译任务
 */
const page = () => {
  return (
    src('src/*.html', { base: 'src' })
      //在里面添加data参数 用于在html模版文件输出
      .pipe(plugin.swig({ data, defaults: { cache: false } }))
      .pipe(dest('temp'))
      .pipe(bs.reload({ stream: true }))
  );
};

//进行image任务编译需要安装imagemin
// yarn add gulp-plugin.imagemin --dev
/**
 * 图片文件编译 图片压缩
 */
const image = () => {
  return src('src/assets/images/**', { base: 'src' }).pipe(plugin.imagemin()).pipe(dest('dist'));
};

/**
 * 字体文件编译
 */
const font = () => {
  return src('src/assets/fonts/**', { base: 'src' }).pipe(plugin.imagemin()).pipe(dest('dist'));
};

/**
 * 其他任务
 * @returns {*}
 */
const extra = () => {
  return src('public/**', { base: 'public' }).pipe(dest('dist'));
};

/**
 * 文件注释编译任务处理
 */
const useref = () => {
  return (
    src('temp/*.html', { base: 'temp' })
      .pipe(plugin.useref({ searchPath: ['temp', '.'] }))
      .pipe(plugin.if(/\.js$/, plugin.uglify()))
      .pipe(plugin.if(/\.css$/, plugin.cleanCss()))
      // .pipe(plugin.if(/\.html$/, plugin.htmlmin()))  //html默认只是将空白字符压缩掉 如果需要将换行符进行压缩 还需要进行配置
      .pipe(
        plugin.if(
          /\.html$/,
          plugin.htmlmin({
            collapseWhitespace: true,
            minifyCSS: true, //将html里的css文件进行压缩
            minifyJs: true, //将html里的js文件进行压缩
          })
        )
      )
      // .pipe(dest('dist'))  //也可以将构建后的文件放在另外的地方
      .pipe(dest('dist'))
  );
};

/**
 * 服务器命令
 */
const serve = () => {
  watch('src/assets/styles/*.scss', style);
  watch('src/assets/scripts/*.js', script);
  watch('src/*.html', page);
  // watch('src/assets/images/**', image)
  // watch('src/assets/fonts/**', font)
  // watch('public/**', extra)
  watch(['src/assets/images/**', 'src/assets/fonts/**', 'public/**'], bs.reload); //reload 也可以理解为一个任务（本质为一个函数）

  // 初始化一个服务器的相关配置
  bs.init({
    notify: false, //服务器链接状态提示 是否开启  false： 如果服务器启动或者页面刷新后不会提示链接信息了
    port: '2080', //browser-async的端口
    // open: false,  //默认浏览器是否打开
    // files: 'dist/**',  //被browser-async监听过后的一个通配符   dist下面的所有文件  可以和bs.reload替换
    server: {
      //需要设置网站的根目录， 去告诉使用着这个目录为根目录
      baseDir: ['temp', 'src', 'public'],
      //用于配置页面的路由 如果网页里面有一些/node_moduls的话会将其指定为routers里面的路由
      //routers里面的配置的优先级高
      routes: {
        '/node_modules': 'node_modules',
      },
    },
  });

  //由于使用useref使目录打包的目录发生了改变（原来的打包目录： dist 现在的打包目录： release）
};

//三个任务需要全部执行
//执行异步任务
//src 下的文件构建
const compile = parallel(style, script, page);

//全部构建
const build = series(clean, parallel(series(compile, useref), extra, image, font));

//开发服务
const develop = series(compile, serve);

module.exports = {
  clean,
  build,
  develop,
  script,
};
